package com.authsphere.security.common.logging.factory;

import com.authsphere.common.constant.Constants;
import com.authsphere.common.enums.ContextHeaderEnum;
import com.authsphere.common.utils.DateUtils;
import com.authsphere.common.utils.JsonUtils;
import com.authsphere.logging.common.entity.LogDetail;
import com.authsphere.plugin.api.context.AuthSphereContext;
import com.google.common.base.Throwables;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.security.core.Authentication;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.Map;
import java.util.Objects;

/**
 * @program: AuthSphere
 * @description:
 * @author: YuKai Fan
 * @create: 2025/3/14 15:21
 **/
public class LogDetailFactory {

    public static LogDetail build(HttpServletRequest request, HttpServletResponse response, Authentication authentication, Object data) {
        return build(request, response, authentication, data, null);
    }

    public static LogDetail build(HttpServletRequest request, HttpServletResponse response, Authentication authentication, Object data, Exception ex) {
        LogDetail logDetail = new LogDetail();
        AuthSphereContext context = (AuthSphereContext) request.getAttribute(Constants.CONTEXT);
        Map<String, String> headers = context.getHeaders();
        logDetail.setTraceId(headers.get(ContextHeaderEnum.TRACE_ID.getHeaderName()));
        logDetail.setModuleType(context.getModule());
        logDetail.setModuleName(context.getModule());
        logDetail.setName(context.getBizName());
        logDetail.setRequestUrl(context.getPath());
        logDetail.setUserIp(request.getRemoteAddr());
        logDetail.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
        logDetail.setRequestData(JsonUtils.toJsonString(context.getRequestData()));
        logDetail.setResultData(JsonUtils.toJsonString(data));
        logDetail.setStartTime(DateUtils.convertToMillis(context.getStartDateTime()));
        logDetail.setDuration(Duration.between(LocalDateTime.now(), context.getStartDateTime()).toMillis());
        if (ex != null) {
            logDetail.setErrorMsg(Throwables.getStackTraceAsString(ex));
        }
        return logDetail;
    }

}
